主要是在分析if-else
判断。
Cython程序分析_5
代码1
1 | def test_del(): |
C文件
1 | +1: def test_del(): |
可见del
仅仅就是将指针置空。
1 | // write access to const memory has been detected, the output may be wrong! |
显然del
指令完全被优化掉了。
代码2
1 | # 外部逻辑 |
C文件
编译后发现,在exec函数和一般函数是不一样的
1 | 01: # 外部逻辑 |
首先把一些函数贴上来。
函数的名称应该不准确,因为这次没有对着C文件嗯看,而是直接根据逻辑大致猜测的。但是意思应该是能理解的。
1 | __int64 __fastcall PyObject_IsTrue_0(__int64 a1) |
exec函数中
1 | if ( (int)PyDict_SetItem(dict_t, var1, int100) < 0 ) |
这两个是
1 | # ... |
根据错误抛出可以得知分别是第二行和第三行代码,且可以发现在exec函数中的变量都是从一个字典里面取出来的。
1 | v32 = strp_var2; |
这是if var2 == "Str"
。先PyDict_GetItem_KnownHash
得到var2
,然后PyUnicode_Equals
来判断是否和"Str"
相等。这个函数已经内联了"Str"
,所以看上去只传了一个参数。
1 | __int64 __fastcall PyUnicode_Equals(__int64 a1) |
然后判断
1 | if ( !v37 ) |
LABEL_248
就是条件为假的位置。
1 | LABEL_248: |
因为条件为假之后就到了函数声明的位置,所以就是这个模样。
1 | tmp = (_QWORD *)PyDict_GetItem_KnownHash(dict_t, var1, *(_QWORD *)(var1 + 24)); |
这是第九行的if var2 == "Str":
,主要是PyObject_RichCompare
函数和PyObject_IsTrue
来进行判断。不过第三个参数是个枚举数,是Py_LE
1 | // object.h |
1 | if ( judge ) |
然后第十行,如果是真,则打印”50”。
后面的总体都差不多,不过是枚举的差异。
1 | if ( v81 ) |
跳到最后一个,else
打印"out"
。
1 | LABEL_230: |
这个便是
1 | var3 = "abc" |
首先PyDict_SetItem
设置变量,然后PyDict_GetItem_KnownHash
取出来,然后PyUnicode_ContainsTF
判断(也是内联过”abc”的)。不过由于if
内是个pass
,所以条件成立后也没什么动作。
函数内
1 | // write access to const memory has been detected, the output may be wrong! |
由于函数内的判断在编译成C文件的时候已经优化成了C的判断形式,所以再加上优化策略,常量传递和死代码消除,其中的一些判断语句完全消失了。不过逻辑还是很清晰。
- 本文作者: Taardis
- 本文链接: https://taardisaa.github.io/2022/02/09/Cython Reverse 5/
- 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!